package studio.raptor.dispatcher.scheduler;

import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import org.apache.curator.framework.recipes.cache.TreeCache;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import studio.raptor.dispatcher.scheduler.config.ServerConfig;
import studio.raptor.dispatcher.scheduler.config.TaskConfig;
import studio.raptor.dispatcher.scheduler.node.DispatcherNode;
import studio.raptor.dispatcher.scheduler.zookeeper.ZookeeperRegistryCenter;

/**
 * 分发调度器
 *
 * @author jack
 * @since 1.0
 */
@Component
public class ServerScheduler {

  private static final Logger log = LoggerFactory.getLogger(ServerScheduler.class);

  TreeCache server2taskCache;

  @Autowired
  ZookeeperRegistryCenter regCenter;

  @Autowired
  ServerConfig serverConfig;


  @PostConstruct
  public void initRegCenter() {
    log.info("init server scheduler...");

    regCenter.init();
    server2taskCache = pathTreeCache();
  }

  @PreDestroy
  public void destory() {

    if (server2taskCache != null) {
      server2taskCache.close();
    }
    regCenter.close();
    log.info("close server scheduler...");

  }

  @Bean
  public TreeCache pathTreeCache() {
    return new TreeCache(regCenter.getClient(), getNodePath());
  }


  /**
   * 将当前分发器可以处理的所有任务上传到注册中心 上传节点：/dispatcher/servers/${server}/ability
   *
   * @param tasks 分发器能处理的接口集合
   * @param server 分发服务，ip-port
   */

  public void uploadServerAbility(List<String> tasks, String server) {
    log.debug("server:{},code:{}", server, tasks.toString());

    String taskPath = String.format(DispatcherNode.SERVER_ABLITY, server);
    regCenter.persistEphemeral(taskPath, tasks.toString());
  }

  public void uploadServerTask(List<String> tasks, String server) {
    log.debug("server:{},code:{}", server, tasks.toString());
    for (String task : tasks) {
      String taskPath = String.format(DispatcherNode.SERVER_2_TASK_NODE, server, task);
      regCenter.persistEphemeral(taskPath, "");
    }
  }

  /**
   * 获取当前分发服务配置的任务
   *
   * @param server 当前分发服务ip-port
   * @return 任务集合
   */
  public List<String> getTasks(String server) {
    String path = String.format(DispatcherNode.SERVER_NODE, server);
    List<String> tasks = regCenter.getChildrenKeys(path);
    List<String> result = new ArrayList<>(tasks.size());
    for (String task : tasks) {
      if (!task.contains("-")) {
        continue;
      }
      String[] codeKindId = task.split("-");
      result.add(codeKindId[0] + "-" + codeKindId[1]);
    }
    return result;
  }

  /**
   * 增加接口配置
   */
  public void addTask(TaskConfig config) {
    String path = String
        .format(DispatcherNode.TASK_NODE, config.getCode() + "-" + config.getKindId());
    boolean isExisted = regCenter.isExisted(path);
    if (!isExisted) {
      regCenter.persist(path, "");
    }
    regCenter.persist(path + "/name", config.getName());
    regCenter.persist(path + "/weight", String.valueOf(config.getWeight()));
    regCenter.persist(path + "/eventName", config.getEventName());
    regCenter.persist(path + "/sort", String.valueOf(config.isSort()));
    regCenter.persist(path + "/eventType", String.valueOf(config.getType()));
  }

  /**
   * 获取任务详情
   *
   * @param code 接口编码
   * @param kindId 事件id
   * @return 任务详情
   */
  public TaskConfig getTaskConfig(String code, Integer kindId) {
    String task = code + "-" + kindId;
    String path = String
        .format(DispatcherNode.TASK_NODE, task);
    boolean isExisted = regCenter.isExisted(path);
    if (!isExisted) {
      throw new RuntimeException("the task config  does not exist");
    }

    TaskConfig taskConfig = new TaskConfig();

    String namePath = String.format(DispatcherNode.TASK_NODE_CONDIG, task, "name");
    String weightPath = String.format(DispatcherNode.TASK_NODE_CONDIG, task, "weight");
    String sortPath = String.format(DispatcherNode.TASK_NODE_CONDIG, task, "sort");
    String typePath = String.format(DispatcherNode.TASK_NODE_CONDIG, task, "eventType");
    String eventNamePath = String.format(DispatcherNode.TASK_NODE_CONDIG, task, "eventName");
    taskConfig.setName(regCenter.getDirectly(namePath));
    taskConfig.setKindId(kindId);
    taskConfig.setType(Integer.valueOf(regCenter.getDirectly(typePath)));
    taskConfig.setWeight(Integer.valueOf(regCenter.getDirectly(weightPath)));
    taskConfig.setSort(Boolean.valueOf(regCenter.getDirectly(sortPath)));
    taskConfig.setCode(code);
    taskConfig.setEventName(regCenter.getDirectly(eventNamePath));
    log.info("the task [{}],config:{}", task, taskConfig);
    return taskConfig;

  }


  private String getNodePath() {
    String server = serverConfig.getHost() + "-" + serverConfig.getPort();
    return String.format(DispatcherNode.SERVER_NODE, server);
  }


}
